package com.x.provider.customer.service.customer;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.x.core.domain.SuggestionTypeEnum;
import com.x.core.utils.BeanUtil;
import com.x.core.utils.CompareUtils;
import com.x.core.utils.MyBatisPlusUtil;
import com.x.core.web.page.PageHelper;
import com.x.core.web.page.PageList;
import com.x.provider.api.customer.model.dto.customer.CustomerResumeAttributeSaveReqDTO;
import com.x.provider.api.customer.model.dto.customer.CustomerResumeSaveReqDTO;
import com.x.provider.api.customer.model.dto.customer.CustomerResumeSearchReqDTO;
import com.x.provider.api.mc.service.MessageRpcService;
import com.x.provider.api.oss.enums.MimeTypeEnum;
import com.x.provider.customer.configure.CustomerApplicationConfig;
import com.x.provider.customer.enums.AttributeKeyGroupEnum;
import com.x.provider.customer.enums.SystemResumeAttributeName;
import com.x.provider.customer.mapper.CustomerResumeMapper;
import com.x.provider.customer.model.domain.common.GenericAttribute;
import com.x.provider.customer.model.domain.customer.CustomerResume;
import com.x.provider.customer.model.query.customer.CustomerResumeQuery;
import com.x.provider.customer.service.common.GenericAttributeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CustomerResumeServiceImpl implements CustomerResumeService{

    private static final Map<String, String> DEFAULT_RESUME_ATTRIBUTE = new HashMap<>();
    private static final Integer TOTAL_RESUME_FIELD_COUNT= 15;
    private final GenericAttributeService genericAttributeService;
    private final CustomerApplicationConfig applicationConfig;
    private final CustomerResumeMapper customerResumeMapper;
    private final MessageRpcService messageRpcService;

    public CustomerResumeServiceImpl(GenericAttributeService genericAttributeService,
                                     CustomerApplicationConfig applicationConfig,
                                     CustomerResumeMapper customerResumeMapper,
                                     MessageRpcService messageRpcService){
        DEFAULT_RESUME_ATTRIBUTE.putAll(Map.of(SystemResumeAttributeName.NICK_NAME.name(), applicationConfig.getDefaultNickName(),
                SystemResumeAttributeName.AVATAR_ID.name(), applicationConfig.getDefaultAvatarId(), SystemResumeAttributeName.PERSONAL_HOMEPAGE_BACKGROUND_ID.name(),
                applicationConfig.getDefaultPersonalHomePageBackgroundId()));
        this.genericAttributeService = genericAttributeService;
        this.applicationConfig = applicationConfig;
        this.customerResumeMapper = customerResumeMapper;
        this.messageRpcService = messageRpcService;
    }

    @Override
    public void setResumeAttribute(CustomerResumeAttributeSaveReqDTO resumeAttributeReqDTO) {
        CustomerResume resume = get(CustomerResumeQuery.builder().customerId(resumeAttributeReqDTO.getCustomerId()).build());
        if (resume == null){
            return;
        }
        SystemResumeAttributeName systemResumeAttributeName = SystemResumeAttributeName.valueOfIfPresent(resumeAttributeReqDTO.getKey());
        if (systemResumeAttributeName != null){
            resumeAttributeReqDTO.setGreenMimeType(systemResumeAttributeName.getGreenDataType().name());
        }
        genericAttributeService.setAttribute(AttributeKeyGroupEnum.RESUME.name(), resume.getCustomerId(), resumeAttributeReqDTO.getKey(), resumeAttributeReqDTO.getValue(),
                MimeTypeEnum.valueOf(resumeAttributeReqDTO.getGreenMimeType()));

    }

    @Override
    public void onResumeDraftAttributeGreenFinished(Long resumeId, SystemResumeAttributeName attributeName, String value, SuggestionTypeEnum suggestionTypeEnum) {

    }

    @Override
    public Map<Long, List<GenericAttribute>> listResumeAttribute(List<Long> resumeIdList, SuggestionTypeEnum suggestionType) {
        return genericAttributeService.listAttributeMap(AttributeKeyGroupEnum.RESUME.toString(), resumeIdList).stream().filter(item -> (
                suggestionType == null || suggestionType.getValue().equals(item.getSuggestionType())))
                .collect(Collectors.groupingBy(item -> item.getEntityId()));
    }

    @Override
    public Map<Long, List<GenericAttribute>> listAndFillDefaultResumeAttribute(List<Long> resumeIdList, SuggestionTypeEnum suggestionType) {
        final Map<Long, List<GenericAttribute>> result = listResumeAttribute(resumeIdList, suggestionType);
        resumeIdList.stream().filter(item -> !result.keySet().contains(item)).forEach(item -> {
            result.put(item, new ArrayList<>());
        });
        result.entrySet().forEach(item -> {
            final Set<String> attributeKeyPassed = item.getValue().stream().filter(opt -> opt.getSuggestionType().equals(SuggestionTypeEnum.PASS.getValue()))
                    .map(GenericAttribute::getKey).collect(Collectors.toSet());
            DEFAULT_RESUME_ATTRIBUTE.entrySet().forEach(opt -> {
                if (attributeKeyPassed.contains(opt.getKey())){
                    return;
                }
                item.getValue().add(GenericAttribute.builder().keyGroup(AttributeKeyGroupEnum.RESUME.name()).key(opt.getKey()).value(opt.getValue()).entityId(item.getKey())
                        .id(0L).suggestionType(SuggestionTypeEnum.PASS.getValue()).build());
            });
        });
        return result;
    }

    @Override
    public Long saveResume(CustomerResumeSaveReqDTO resumeSaveReqDTO) {
        CustomerResume customerResumeExisted = get(CustomerResumeQuery.builder().customerId(resumeSaveReqDTO.getCustomerId()).build());
        if (customerResumeExisted != null){
            BeanUtil.prepare(resumeSaveReqDTO, customerResumeExisted);
        }
        else{
            customerResumeExisted = BeanUtil.prepare(resumeSaveReqDTO, CustomerResume.class);
        }
        customerResumeExisted.setResumeFillRatio(getResumeFillRatio(customerResumeExisted));
        MyBatisPlusUtil.save(customerResumeMapper, customerResumeExisted);
        return customerResumeExisted.getId();
    }


    @Override
    public List<CustomerResume> listResume(List<Long> customerIdList) {
        return list(CustomerResumeQuery.builder().customerIdList(customerIdList).build());
    }

    @Override
    public PageList<CustomerResume> listResume(CustomerResumeSearchReqDTO reqDTO) {
        CustomerResumeQuery query = CustomerResumeQuery.builder().gender(reqDTO.getGender()).visible(true)
                .pageLimit(PageHelper.toPageLimit(reqDTO.getPageDomain()))
                .build();
        if (reqDTO.getPageDomain().getNullableCursor() != null){
            query.setLtId(reqDTO.getPageDomain().getNullableCursor());
        }
        List<CustomerResume> customerResumes = customerResumeMapper.selectList(build(query).orderByDesc(CustomerResume::getId));
        if (customerResumes.isEmpty()){
            return new PageList<>();
        }
        return new PageList<>(customerResumes, reqDTO.getPageDomain().getPageSize(), CollectionUtils.lastElement(customerResumes).getId());
    }

    List<CustomerResume> list(CustomerResumeQuery customerResumeQuery){
        return customerResumeMapper.selectList(build(customerResumeQuery));
    }

    public CustomerResume get(CustomerResumeQuery query){
        return customerResumeMapper.selectOne(build(query));
    }

    private LambdaQueryWrapper<CustomerResume> build(CustomerResumeQuery query){
        LambdaQueryWrapper<CustomerResume> queryWrapper = new LambdaQueryWrapper<>();
        if (query.getId() != null){
            queryWrapper.eq(CustomerResume::getId, query.getId());
        }
        if (!CollectionUtils.isEmpty(query.getIdList())){
            queryWrapper.in(CustomerResume::getId, query.getIdList());
        }
        if (query.getCustomerId() != null){
            queryWrapper.eq(CustomerResume::getCustomerId, query.getCustomerId());
        }
        if (!CollectionUtils.isEmpty(query.getCustomerIdList())){
            queryWrapper.in(CustomerResume::getCustomerId, query.getCustomerIdList());
        }
        if (query.getPageLimit() != null){
            queryWrapper.last(PageHelper.toPageLimitSql(query.getPageLimit()));
        }
        if (query.getLtId() != null){
            queryWrapper.lt(CustomerResume::getId, query.getLtId());
        }
        if (query.getGender() != null){
            queryWrapper.eq(CustomerResume::getGender, query.getGender());
        }
        if (query.getVisible() != null){
            queryWrapper.eq(CustomerResume::getVisible, query.getVisible());
        }
        return queryWrapper;
    }

    public static Float getResumeFillRatio(CustomerResume customerResume){
        int fillCount = 0;
        if (CompareUtils.isEmptyOrZero(customerResume.getBirthdayYear())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getCarCount())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getChildren())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getConstellation())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getDegreeHighest())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getDrink())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getEthnicity())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getExpectWeddingDate())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getGender())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getHeight())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getHouse())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getMarriageStatus())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getNativeRegionId())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getOccupation())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getPublisherType())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getRegionIdLevel1())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getRegionIdLevel2())){
            fillCount ++;
        }
        if (CompareUtils.isEmptyOrZero(customerResume.getRegionIdLevel3())){
            fillCount ++;
        }
        Float result = (float)fillCount / (float)TOTAL_RESUME_FIELD_COUNT;

        return result.compareTo(1.0f) > 0 ? 1.0f : result ;
    }
}
